blob: 733ba96186e7592a7428f0a073885343d9a0825f [file] [log] [blame]
Henry Ptasinskicf2b4482010-09-20 22:33:12 -07001/*
2 * Copyright (c) 2010 Broadcom Corporation
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16/* ****************** BCMSDH Interface Functions *************************** */
17
Greg Kroah-Hartmana1c16ed2010-10-21 11:17:44 -070018#include <linux/types.h>
Brett Rudleyc6ac24e2010-10-26 11:55:23 -070019#include <linux/netdevice.h>
Stanislav Fomichevbe1c09f2011-03-28 01:31:36 +040020#include <linux/pci_ids.h>
Franky Lin7c6100e2011-06-01 13:45:36 +020021#include <linux/sched.h>
Roland Vossenc4daa842011-06-09 16:44:50 +020022
Roland Vossencc3cea52011-06-01 13:45:59 +020023#include <defs.h>
24#include <brcm_hw_ids.h>
Roland Vossenf97e9562011-06-01 13:45:52 +020025#include <brcmu_utils.h>
26#include <brcmu_wifi.h>
Roland Vossencc3cea52011-06-01 13:45:59 +020027#include <soc.h>
Roland Vossenc4daa842011-06-09 16:44:50 +020028#include "bcmsdbus.h" /* common SDIO/controller interface */
29#include "sbsdio.h" /* BRCM sdio device core */
Roland Vossen13f401c2011-05-03 11:35:52 +020030#include "dngl_stats.h"
31#include "dhd.h"
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070032
33#define SDIOH_API_ACCESS_RETRY_LIMIT 2
34const uint bcmsdh_msglevel = BCMSDH_ERROR_VAL;
35
Roland Vossen677226a2011-06-29 16:47:21 -070036struct brcmf_sdio {
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070037 bool init_success; /* underlying driver successfully attached */
38 void *sdioh; /* handler for sdioh */
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -070039 u32 vendevid; /* Target Vendor and Device ID on SD bus */
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070040 bool regfail; /* Save status of last
41 reg_read/reg_write call */
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -070042 u32 sbwad; /* Save backplane window address */
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070043};
44/* local copy of bcm sd handler */
Roland Vossen677226a2011-06-29 16:47:21 -070045struct brcmf_sdio *l_bcmsdh;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070046
47#if defined(OOB_INTR_ONLY) && defined(HW_OOB)
Roland Vossen54ca2962011-06-29 16:46:59 -070048extern int brcmf_sdioh_enable_hw_oob_intr(void *sdioh, bool enable);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070049
Roland Vossen677226a2011-06-29 16:47:21 -070050void brcmf_sdcard_enable_hw_oob_intr(struct brcmf_sdio *sdh, bool enable)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070051{
Roland Vossen54ca2962011-06-29 16:46:59 -070052 brcmf_sdioh_enable_hw_oob_intr(sdh->sdioh, enable);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070053}
54#endif
55
Roland Vossen677226a2011-06-29 16:47:21 -070056struct brcmf_sdio *brcmf_sdcard_attach(void *cfghdl, void **regsva, uint irq)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070057{
Roland Vossen677226a2011-06-29 16:47:21 -070058 struct brcmf_sdio *bcmsdh;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070059
Roland Vossen677226a2011-06-29 16:47:21 -070060 bcmsdh = kzalloc(sizeof(struct brcmf_sdio), GFP_ATOMIC);
Jason Cooperc74c95c2010-09-30 15:15:35 -040061 if (bcmsdh == NULL) {
mike.rapoport@gmail.com97e17d02010-10-13 00:09:09 +020062 BCMSDH_ERROR(("bcmsdh_attach: out of memory"));
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070063 return NULL;
64 }
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070065
66 /* save the handler locally */
67 l_bcmsdh = bcmsdh;
68
Roland Vossen54ca2962011-06-29 16:46:59 -070069 bcmsdh->sdioh = brcmf_sdioh_attach(cfghdl, irq);
Jason Cooperc74c95c2010-09-30 15:15:35 -040070 if (!bcmsdh->sdioh) {
Roland Vossen54ca2962011-06-29 16:46:59 -070071 brcmf_sdcard_detach(bcmsdh);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070072 return NULL;
73 }
74
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -070075 bcmsdh->init_success = true;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070076
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -070077 *regsva = (u32 *) SI_ENUM_BASE;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070078
79 /* Report the BAR, to fix if needed */
80 bcmsdh->sbwad = SI_ENUM_BASE;
81 return bcmsdh;
82}
83
Roland Vossen54ca2962011-06-29 16:46:59 -070084int brcmf_sdcard_detach(void *sdh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070085{
Roland Vossen677226a2011-06-29 16:47:21 -070086 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070087
88 if (bcmsdh != NULL) {
89 if (bcmsdh->sdioh) {
Roland Vossen54ca2962011-06-29 16:46:59 -070090 brcmf_sdioh_detach(bcmsdh->sdioh);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070091 bcmsdh->sdioh = NULL;
92 }
mike.rapoport@gmail.com182acb32010-10-13 00:09:12 +020093 kfree(bcmsdh);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070094 }
95
96 l_bcmsdh = NULL;
97 return 0;
98}
99
100int
Roland Vossen54ca2962011-06-29 16:46:59 -0700101brcmf_sdcard_iovar_op(void *sdh, const char *name,
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700102 void *params, int plen, void *arg, int len, bool set)
103{
Roland Vossen677226a2011-06-29 16:47:21 -0700104 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Roland Vossen54ca2962011-06-29 16:46:59 -0700105 return brcmf_sdioh_iovar_op(bcmsdh->sdioh, name, params, plen, arg,
106 len, set);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700107}
108
Roland Vossen54ca2962011-06-29 16:46:59 -0700109bool brcmf_sdcard_intr_query(void *sdh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700110{
Roland Vossen677226a2011-06-29 16:47:21 -0700111 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Roland Vossen3c793822011-06-29 16:47:23 -0700112 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700113 bool on;
114
115 ASSERT(bcmsdh);
Roland Vossen54ca2962011-06-29 16:46:59 -0700116 status = brcmf_sdioh_interrupt_query(bcmsdh->sdioh, &on);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700117 if (SDIOH_API_SUCCESS(status))
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -0700118 return false;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700119 else
120 return on;
121}
122
Roland Vossen54ca2962011-06-29 16:46:59 -0700123int brcmf_sdcard_intr_enable(void *sdh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700124{
Roland Vossen677226a2011-06-29 16:47:21 -0700125 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Roland Vossen3c793822011-06-29 16:47:23 -0700126 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700127 ASSERT(bcmsdh);
128
Roland Vossen54ca2962011-06-29 16:46:59 -0700129 status = brcmf_sdioh_interrupt_set(bcmsdh->sdioh, true);
Roland Vossen1bc93ce2011-05-03 11:35:21 +0200130 return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700131}
132
Roland Vossen54ca2962011-06-29 16:46:59 -0700133int brcmf_sdcard_intr_disable(void *sdh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700134{
Roland Vossen677226a2011-06-29 16:47:21 -0700135 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Roland Vossen3c793822011-06-29 16:47:23 -0700136 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700137 ASSERT(bcmsdh);
138
Roland Vossen54ca2962011-06-29 16:46:59 -0700139 status = brcmf_sdioh_interrupt_set(bcmsdh->sdioh, false);
Roland Vossen1bc93ce2011-05-03 11:35:21 +0200140 return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700141}
142
Roland Vossen54ca2962011-06-29 16:46:59 -0700143int brcmf_sdcard_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700144{
Roland Vossen677226a2011-06-29 16:47:21 -0700145 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Roland Vossen3c793822011-06-29 16:47:23 -0700146 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700147 ASSERT(bcmsdh);
148
Roland Vossen54ca2962011-06-29 16:46:59 -0700149 status = brcmf_sdioh_interrupt_register(bcmsdh->sdioh, fn, argh);
Roland Vossen1bc93ce2011-05-03 11:35:21 +0200150 return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700151}
152
Roland Vossen54ca2962011-06-29 16:46:59 -0700153int brcmf_sdcard_intr_dereg(void *sdh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700154{
Roland Vossen677226a2011-06-29 16:47:21 -0700155 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Roland Vossen3c793822011-06-29 16:47:23 -0700156 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700157 ASSERT(bcmsdh);
158
Roland Vossen54ca2962011-06-29 16:46:59 -0700159 status = brcmf_sdioh_interrupt_deregister(bcmsdh->sdioh);
Roland Vossen1bc93ce2011-05-03 11:35:21 +0200160 return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700161}
162
163#if defined(DHD_DEBUG)
Roland Vossen54ca2962011-06-29 16:46:59 -0700164bool brcmf_sdcard_intr_pending(void *sdh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700165{
Roland Vossen677226a2011-06-29 16:47:21 -0700166 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700167
168 ASSERT(sdh);
Roland Vossen54ca2962011-06-29 16:46:59 -0700169 return brcmf_sdioh_interrupt_pending(bcmsdh->sdioh);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700170}
171#endif
172
Roland Vossen54ca2962011-06-29 16:46:59 -0700173int brcmf_sdcard_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700174{
175 ASSERT(sdh);
176
177 /* don't support yet */
Roland Vossene10d82d2011-05-03 11:35:19 +0200178 return -ENOTSUPP;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700179}
180
Roland Vossen54ca2962011-06-29 16:46:59 -0700181u8 brcmf_sdcard_cfg_read(void *sdh, uint fnc_num, u32 addr, int *err)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700182{
Roland Vossen677226a2011-06-29 16:47:21 -0700183 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Roland Vossen3c793822011-06-29 16:47:23 -0700184 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700185#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -0700186 s32 retry = 0;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700187#endif
Greg Kroah-Hartman3fd79f72010-10-05 10:11:12 -0700188 u8 data = 0;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700189
190 if (!bcmsdh)
191 bcmsdh = l_bcmsdh;
192
193 ASSERT(bcmsdh->init_success);
194
195#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
196 do {
197 if (retry) /* wait for 1 ms till bus get settled down */
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +0200198 udelay(1000);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700199#endif
200 status =
Roland Vossen54ca2962011-06-29 16:46:59 -0700201 brcmf_sdioh_cfg_read(bcmsdh->sdioh, fnc_num, addr,
Greg Kroah-Hartman3fd79f72010-10-05 10:11:12 -0700202 (u8 *) &data);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700203#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
204 } while (!SDIOH_API_SUCCESS(status)
205 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
206#endif
207 if (err)
Roland Vossenb74ac122011-05-03 11:35:20 +0200208 *err = (SDIOH_API_SUCCESS(status) ? 0 : -EIO);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700209
Greg Kroah-Hartman3fd79f72010-10-05 10:11:12 -0700210 BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700211 __func__, fnc_num, addr, data));
212
213 return data;
214}
215
216void
Roland Vossen54ca2962011-06-29 16:46:59 -0700217brcmf_sdcard_cfg_write(void *sdh, uint fnc_num, u32 addr, u8 data, int *err)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700218{
Roland Vossen677226a2011-06-29 16:47:21 -0700219 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Roland Vossen3c793822011-06-29 16:47:23 -0700220 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700221#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -0700222 s32 retry = 0;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700223#endif
224
225 if (!bcmsdh)
226 bcmsdh = l_bcmsdh;
227
228 ASSERT(bcmsdh->init_success);
229
230#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
231 do {
232 if (retry) /* wait for 1 ms till bus get settled down */
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +0200233 udelay(1000);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700234#endif
235 status =
Roland Vossen54ca2962011-06-29 16:46:59 -0700236 brcmf_sdioh_cfg_write(bcmsdh->sdioh, fnc_num, addr,
Greg Kroah-Hartman3fd79f72010-10-05 10:11:12 -0700237 (u8 *) &data);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700238#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
239 } while (!SDIOH_API_SUCCESS(status)
240 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
241#endif
242 if (err)
Roland Vossenb74ac122011-05-03 11:35:20 +0200243 *err = SDIOH_API_SUCCESS(status) ? 0 : -EIO;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700244
Greg Kroah-Hartman3fd79f72010-10-05 10:11:12 -0700245 BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700246 __func__, fnc_num, addr, data));
247}
248
Roland Vossen54ca2962011-06-29 16:46:59 -0700249u32 brcmf_sdcard_cfg_read_word(void *sdh, uint fnc_num, u32 addr, int *err)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700250{
Roland Vossen677226a2011-06-29 16:47:21 -0700251 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Roland Vossen3c793822011-06-29 16:47:23 -0700252 int status;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -0700253 u32 data = 0;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700254
255 if (!bcmsdh)
256 bcmsdh = l_bcmsdh;
257
258 ASSERT(bcmsdh->init_success);
259
Roland Vossen54ca2962011-06-29 16:46:59 -0700260 status = brcmf_sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
261 SDIOH_READ, fnc_num, addr, &data, 4);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700262
263 if (err)
Roland Vossenb74ac122011-05-03 11:35:20 +0200264 *err = (SDIOH_API_SUCCESS(status) ? 0 : -EIO);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700265
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -0700266 BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700267 __func__, fnc_num, addr, data));
268
269 return data;
270}
271
272void
Roland Vossen54ca2962011-06-29 16:46:59 -0700273brcmf_sdcard_cfg_write_word(void *sdh, uint fnc_num, u32 addr, u32 data,
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700274 int *err)
275{
Roland Vossen677226a2011-06-29 16:47:21 -0700276 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Roland Vossen3c793822011-06-29 16:47:23 -0700277 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700278
279 if (!bcmsdh)
280 bcmsdh = l_bcmsdh;
281
282 ASSERT(bcmsdh->init_success);
283
284 status =
Roland Vossen54ca2962011-06-29 16:46:59 -0700285 brcmf_sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700286 SDIOH_WRITE, fnc_num, addr, &data, 4);
287
288 if (err)
Roland Vossenb74ac122011-05-03 11:35:20 +0200289 *err = (SDIOH_API_SUCCESS(status) ? 0 : -EIO);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700290
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -0700291 BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700292 __func__, fnc_num, addr, data));
293}
294
Roland Vossen54ca2962011-06-29 16:46:59 -0700295int brcmf_sdcard_cis_read(void *sdh, uint func, u8 * cis, uint length)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700296{
Roland Vossen677226a2011-06-29 16:47:21 -0700297 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Roland Vossen3c793822011-06-29 16:47:23 -0700298 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700299
Greg Kroah-Hartman3fd79f72010-10-05 10:11:12 -0700300 u8 *tmp_buf, *tmp_ptr;
301 u8 *ptr;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700302 bool ascii = func & ~0xf;
303 func &= 0x7;
304
305 if (!bcmsdh)
306 bcmsdh = l_bcmsdh;
307
308 ASSERT(bcmsdh->init_success);
309 ASSERT(cis);
310 ASSERT(length <= SBSDIO_CIS_SIZE_LIMIT);
311
Roland Vossen54ca2962011-06-29 16:46:59 -0700312 status = brcmf_sdioh_cis_read(bcmsdh->sdioh, func, cis, length);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700313
314 if (ascii) {
315 /* Move binary bits to tmp and format them
316 into the provided buffer. */
mike.rapoport@gmail.com5fcc1fc2010-10-13 00:09:10 +0200317 tmp_buf = kmalloc(length, GFP_ATOMIC);
Jason Cooperc74c95c2010-09-30 15:15:35 -0400318 if (tmp_buf == NULL) {
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700319 BCMSDH_ERROR(("%s: out of memory\n", __func__));
Roland Vossene10d82d2011-05-03 11:35:19 +0200320 return -ENOMEM;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700321 }
Stanislav Fomichev02160692011-02-15 01:05:10 +0300322 memcpy(tmp_buf, cis, length);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700323 for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4);
324 tmp_ptr++) {
325 ptr += sprintf((char *)ptr, "%.2x ", *tmp_ptr & 0xff);
326 if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0)
327 ptr += sprintf((char *)ptr, "\n");
328 }
mike.rapoport@gmail.com182acb32010-10-13 00:09:12 +0200329 kfree(tmp_buf);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700330 }
331
Roland Vossen1bc93ce2011-05-03 11:35:21 +0200332 return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700333}
334
Roland Vossen54ca2962011-06-29 16:46:59 -0700335static int brcmf_sdcard_set_sbaddr_window(void *sdh, u32 address)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700336{
337 int err = 0;
Roland Vossen677226a2011-06-29 16:47:21 -0700338 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Roland Vossen54ca2962011-06-29 16:46:59 -0700339 brcmf_sdcard_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700340 (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
341 if (!err)
Roland Vossen54ca2962011-06-29 16:46:59 -0700342 brcmf_sdcard_cfg_write(bcmsdh, SDIO_FUNC_1,
343 SBSDIO_FUNC1_SBADDRMID,
344 (address >> 16) & SBSDIO_SBADDRMID_MASK,
345 &err);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700346 if (!err)
Roland Vossen54ca2962011-06-29 16:46:59 -0700347 brcmf_sdcard_cfg_write(bcmsdh, SDIO_FUNC_1,
348 SBSDIO_FUNC1_SBADDRHIGH,
349 (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
350 &err);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700351
352 return err;
353}
354
Roland Vossen54ca2962011-06-29 16:46:59 -0700355u32 brcmf_sdcard_reg_read(void *sdh, u32 addr, uint size)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700356{
Roland Vossen677226a2011-06-29 16:47:21 -0700357 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Roland Vossen3c793822011-06-29 16:47:23 -0700358 int status;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -0700359 u32 word = 0;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700360 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
361
362 BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, ", __func__, addr));
363
364 if (!bcmsdh)
365 bcmsdh = l_bcmsdh;
366
367 ASSERT(bcmsdh->init_success);
368
369 if (bar0 != bcmsdh->sbwad) {
Roland Vossen54ca2962011-06-29 16:46:59 -0700370 if (brcmf_sdcard_set_sbaddr_window(bcmsdh, bar0))
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700371 return 0xFFFFFFFF;
372
373 bcmsdh->sbwad = bar0;
374 }
375
376 addr &= SBSDIO_SB_OFT_ADDR_MASK;
377 if (size == 4)
378 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
379
Roland Vossen54ca2962011-06-29 16:46:59 -0700380 status = brcmf_sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700381 SDIOH_READ, SDIO_FUNC_1, addr, &word, size);
382
383 bcmsdh->regfail = !(SDIOH_API_SUCCESS(status));
384
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -0700385 BCMSDH_INFO(("u32data = 0x%x\n", word));
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700386
387 /* if ok, return appropriately masked word */
388 if (SDIOH_API_SUCCESS(status)) {
389 switch (size) {
Greg Kroah-Hartman3fd79f72010-10-05 10:11:12 -0700390 case sizeof(u8):
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700391 return word & 0xff;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700392 case sizeof(u16):
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700393 return word & 0xffff;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -0700394 case sizeof(u32):
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700395 return word;
396 default:
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -0700397 bcmsdh->regfail = true;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700398
399 }
400 }
401
402 /* otherwise, bad sdio access or invalid size */
403 BCMSDH_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__,
404 addr, size));
405 return 0xFFFFFFFF;
406}
407
Roland Vossen54ca2962011-06-29 16:46:59 -0700408u32 brcmf_sdcard_reg_write(void *sdh, u32 addr, uint size, u32 data)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700409{
Roland Vossen677226a2011-06-29 16:47:21 -0700410 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Roland Vossen3c793822011-06-29 16:47:23 -0700411 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700412 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
413 int err = 0;
414
415 BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
416 __func__, addr, size * 8, data));
417
418 if (!bcmsdh)
419 bcmsdh = l_bcmsdh;
420
421 ASSERT(bcmsdh->init_success);
422
423 if (bar0 != bcmsdh->sbwad) {
Roland Vossen54ca2962011-06-29 16:46:59 -0700424 err = brcmf_sdcard_set_sbaddr_window(bcmsdh, bar0);
Jason Cooperc74c95c2010-09-30 15:15:35 -0400425 if (err)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700426 return err;
427
428 bcmsdh->sbwad = bar0;
429 }
430
431 addr &= SBSDIO_SB_OFT_ADDR_MASK;
432 if (size == 4)
433 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
434 status =
Roland Vossen54ca2962011-06-29 16:46:59 -0700435 brcmf_sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL,
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700436 SDIOH_WRITE, SDIO_FUNC_1, addr, &data, size);
437 bcmsdh->regfail = !(SDIOH_API_SUCCESS(status));
438
439 if (SDIOH_API_SUCCESS(status))
440 return 0;
441
442 BCMSDH_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
443 __func__, data, addr, size));
444 return 0xFFFFFFFF;
445}
446
Roland Vossen54ca2962011-06-29 16:46:59 -0700447bool brcmf_sdcard_regfail(void *sdh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700448{
Roland Vossen677226a2011-06-29 16:47:21 -0700449 return ((struct brcmf_sdio *) sdh)->regfail;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700450}
451
452int
Roland Vossen677226a2011-06-29 16:47:21 -0700453brcmf_sdcard_recv_buf(struct brcmf_sdio *bcmsdh, u32 addr, uint fn, uint flags,
Arend van Sprielc26b1372010-11-23 14:06:23 +0100454 u8 *buf, uint nbytes, struct sk_buff *pkt,
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700455 bcmsdh_cmplt_fn_t complete, void *handle)
456{
Roland Vossen3c793822011-06-29 16:47:23 -0700457 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700458 uint incr_fix;
459 uint width;
460 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
461 int err = 0;
462
463 ASSERT(bcmsdh);
464 ASSERT(bcmsdh->init_success);
465
466 BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
467 __func__, fn, addr, nbytes));
468
469 /* Async not implemented yet */
470 ASSERT(!(flags & SDIO_REQ_ASYNC));
471 if (flags & SDIO_REQ_ASYNC)
Roland Vossene10d82d2011-05-03 11:35:19 +0200472 return -ENOTSUPP;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700473
474 if (bar0 != bcmsdh->sbwad) {
Roland Vossen54ca2962011-06-29 16:46:59 -0700475 err = brcmf_sdcard_set_sbaddr_window(bcmsdh, bar0);
Jason Cooperc74c95c2010-09-30 15:15:35 -0400476 if (err)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700477 return err;
478
479 bcmsdh->sbwad = bar0;
480 }
481
482 addr &= SBSDIO_SB_OFT_ADDR_MASK;
483
484 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
485 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
486 if (width == 4)
487 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
488
Roland Vossen54ca2962011-06-29 16:46:59 -0700489 status = brcmf_sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO,
490 incr_fix, SDIOH_READ, fn, addr, width, nbytes, buf, pkt);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700491
Roland Vossenb74ac122011-05-03 11:35:20 +0200492 return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700493}
494
495int
Roland Vossen54ca2962011-06-29 16:46:59 -0700496brcmf_sdcard_send_buf(void *sdh, u32 addr, uint fn, uint flags,
Greg Kroah-Hartman3fd79f72010-10-05 10:11:12 -0700497 u8 *buf, uint nbytes, void *pkt,
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700498 bcmsdh_cmplt_fn_t complete, void *handle)
499{
Roland Vossen677226a2011-06-29 16:47:21 -0700500 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Roland Vossen3c793822011-06-29 16:47:23 -0700501 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700502 uint incr_fix;
503 uint width;
504 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
505 int err = 0;
506
507 ASSERT(bcmsdh);
508 ASSERT(bcmsdh->init_success);
509
510 BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
511 __func__, fn, addr, nbytes));
512
513 /* Async not implemented yet */
514 ASSERT(!(flags & SDIO_REQ_ASYNC));
515 if (flags & SDIO_REQ_ASYNC)
Roland Vossene10d82d2011-05-03 11:35:19 +0200516 return -ENOTSUPP;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700517
518 if (bar0 != bcmsdh->sbwad) {
Roland Vossen54ca2962011-06-29 16:46:59 -0700519 err = brcmf_sdcard_set_sbaddr_window(bcmsdh, bar0);
Jason Cooperc74c95c2010-09-30 15:15:35 -0400520 if (err)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700521 return err;
522
523 bcmsdh->sbwad = bar0;
524 }
525
526 addr &= SBSDIO_SB_OFT_ADDR_MASK;
527
528 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
529 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
530 if (width == 4)
531 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
532
Roland Vossen54ca2962011-06-29 16:46:59 -0700533 status = brcmf_sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO,
534 incr_fix, SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700535
Roland Vossen1bc93ce2011-05-03 11:35:21 +0200536 return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700537}
538
Roland Vossen54ca2962011-06-29 16:46:59 -0700539int brcmf_sdcard_rwdata(void *sdh, uint rw, u32 addr, u8 *buf, uint nbytes)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700540{
Roland Vossen677226a2011-06-29 16:47:21 -0700541 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Roland Vossen3c793822011-06-29 16:47:23 -0700542 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700543
544 ASSERT(bcmsdh);
545 ASSERT(bcmsdh->init_success);
546 ASSERT((addr & SBSDIO_SBWINDOW_MASK) == 0);
547
548 addr &= SBSDIO_SB_OFT_ADDR_MASK;
549 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
550
Roland Vossen54ca2962011-06-29 16:46:59 -0700551 status = brcmf_sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO,
552 SDIOH_DATA_INC, (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
553 addr, 4, nbytes, buf, NULL);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700554
Roland Vossen1bc93ce2011-05-03 11:35:21 +0200555 return SDIOH_API_SUCCESS(status) ? 0 : -EIO;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700556}
557
Roland Vossen54ca2962011-06-29 16:46:59 -0700558int brcmf_sdcard_abort(void *sdh, uint fn)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700559{
Roland Vossen677226a2011-06-29 16:47:21 -0700560 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700561
Roland Vossen54ca2962011-06-29 16:46:59 -0700562 return brcmf_sdioh_abort(bcmsdh->sdioh, fn);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700563}
564
Roland Vossen54ca2962011-06-29 16:46:59 -0700565int brcmf_sdcard_start(void *sdh, int stage)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700566{
Roland Vossen677226a2011-06-29 16:47:21 -0700567 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700568
Roland Vossen54ca2962011-06-29 16:46:59 -0700569 return brcmf_sdioh_start(bcmsdh->sdioh, stage);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700570}
571
Roland Vossen54ca2962011-06-29 16:46:59 -0700572int brcmf_sdcard_stop(void *sdh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700573{
Roland Vossen677226a2011-06-29 16:47:21 -0700574 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700575
Roland Vossen54ca2962011-06-29 16:46:59 -0700576 return brcmf_sdioh_stop(bcmsdh->sdioh);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700577}
578
Roland Vossen54ca2962011-06-29 16:46:59 -0700579int brcmf_sdcard_query_device(void *sdh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700580{
Roland Vossen677226a2011-06-29 16:47:21 -0700581 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Stanislav Fomichevbe1c09f2011-03-28 01:31:36 +0400582 bcmsdh->vendevid = (PCI_VENDOR_ID_BROADCOM << 16) | 0;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700583 return bcmsdh->vendevid;
584}
585
Roland Vossen54ca2962011-06-29 16:46:59 -0700586uint brcmf_sdcard_query_iofnum(void *sdh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700587{
Roland Vossen677226a2011-06-29 16:47:21 -0700588 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700589
590 if (!bcmsdh)
591 bcmsdh = l_bcmsdh;
592
Roland Vossen54ca2962011-06-29 16:46:59 -0700593 return brcmf_sdioh_query_iofnum(bcmsdh->sdioh);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700594}
595
Roland Vossen677226a2011-06-29 16:47:21 -0700596int brcmf_sdcard_reset(struct brcmf_sdio *sdh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700597{
Roland Vossen677226a2011-06-29 16:47:21 -0700598 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700599
Roland Vossen54ca2962011-06-29 16:46:59 -0700600 return brcmf_sdioh_reset(bcmsdh->sdioh);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700601}
602
Roland Vossen677226a2011-06-29 16:47:21 -0700603void *brcmf_sdcard_get_sdioh(struct brcmf_sdio *sdh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700604{
605 ASSERT(sdh);
606 return sdh->sdioh;
607}
608
609/* Function to pass device-status bits to DHD. */
Roland Vossen54ca2962011-06-29 16:46:59 -0700610u32 brcmf_sdcard_get_dstatus(void *sdh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700611{
612 return 0;
613}
614
Roland Vossen54ca2962011-06-29 16:46:59 -0700615u32 brcmf_sdcard_cur_sbwad(void *sdh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700616{
Roland Vossen677226a2011-06-29 16:47:21 -0700617 struct brcmf_sdio *bcmsdh = (struct brcmf_sdio *) sdh;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700618
619 if (!bcmsdh)
620 bcmsdh = l_bcmsdh;
621
622 return bcmsdh->sbwad;
623}
624
Roland Vossen54ca2962011-06-29 16:46:59 -0700625void brcmf_sdcard_chipinfo(void *sdh, u32 chip, u32 chiprev)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700626{
627 return;
628}