blob: 11abd552fdf36797d4707ca11067ac9e220d4ea4 [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 */
Roland Vossen127aa5c2011-07-05 22:05:58 +020016/* ****************** SDIO CARD Interface Functions **************************/
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070017
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
Roland Vossen62dd6562011-07-05 22:05:57 +020034const uint brcmf_sdio_msglevel = BRCMF_SD_ERROR_VAL;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070035
Roland Vossen127aa5c2011-07-05 22:05:58 +020036struct brcmf_sdio_card {
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 Vossen127aa5c2011-07-05 22:05:58 +020045static struct brcmf_sdio_card *l_card;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070046
Roland Vossen127aa5c2011-07-05 22:05:58 +020047struct brcmf_sdio_card*
48brcmf_sdcard_attach(void *cfghdl, void **regsva, uint irq)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070049{
Roland Vossen127aa5c2011-07-05 22:05:58 +020050 struct brcmf_sdio_card *card;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070051
Roland Vossen127aa5c2011-07-05 22:05:58 +020052 card = kzalloc(sizeof(struct brcmf_sdio_card), GFP_ATOMIC);
Roland Vossen62dd6562011-07-05 22:05:57 +020053 if (card == NULL) {
54 BRCMF_SD_ERROR(("sdcard_attach: out of memory"));
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070055 return NULL;
56 }
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070057
58 /* save the handler locally */
Roland Vossen62dd6562011-07-05 22:05:57 +020059 l_card = card;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070060
Roland Vossen62dd6562011-07-05 22:05:57 +020061 card->sdioh = brcmf_sdioh_attach(cfghdl, irq);
62 if (!card->sdioh) {
63 brcmf_sdcard_detach(card);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070064 return NULL;
65 }
66
Roland Vossen62dd6562011-07-05 22:05:57 +020067 card->init_success = true;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070068
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -070069 *regsva = (u32 *) SI_ENUM_BASE;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070070
71 /* Report the BAR, to fix if needed */
Roland Vossen62dd6562011-07-05 22:05:57 +020072 card->sbwad = SI_ENUM_BASE;
73 return card;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070074}
75
Roland Vossen127aa5c2011-07-05 22:05:58 +020076int brcmf_sdcard_detach(struct brcmf_sdio_card *card)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070077{
Roland Vossen62dd6562011-07-05 22:05:57 +020078 if (card != NULL) {
79 if (card->sdioh) {
80 brcmf_sdioh_detach(card->sdioh);
81 card->sdioh = NULL;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070082 }
Roland Vossen62dd6562011-07-05 22:05:57 +020083 kfree(card);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070084 }
85
Roland Vossen62dd6562011-07-05 22:05:57 +020086 l_card = NULL;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070087 return 0;
88}
89
90int
Roland Vossen127aa5c2011-07-05 22:05:58 +020091brcmf_sdcard_iovar_op(struct brcmf_sdio_card *card, const char *name,
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070092 void *params, int plen, void *arg, int len, bool set)
93{
Roland Vossen62dd6562011-07-05 22:05:57 +020094 return brcmf_sdioh_iovar_op(card->sdioh, name, params, plen, arg,
Roland Vossen54ca2962011-06-29 16:46:59 -070095 len, set);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070096}
97
Roland Vossen127aa5c2011-07-05 22:05:58 +020098bool brcmf_sdcard_intr_query(struct brcmf_sdio_card *card)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -070099{
Roland Vossen3c793822011-06-29 16:47:23 -0700100 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700101 bool on;
102
Roland Vossen62dd6562011-07-05 22:05:57 +0200103 ASSERT(card);
104 status = brcmf_sdioh_interrupt_query(card->sdioh, &on);
Roland Vossen67f72be2011-06-29 16:47:56 -0700105 if (status == 0)
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -0700106 return false;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700107 else
108 return on;
109}
110
Roland Vossen127aa5c2011-07-05 22:05:58 +0200111int brcmf_sdcard_intr_enable(struct brcmf_sdio_card *card)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700112{
Roland Vossen62dd6562011-07-05 22:05:57 +0200113 ASSERT(card);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700114
Roland Vossen62dd6562011-07-05 22:05:57 +0200115 return brcmf_sdioh_interrupt_set(card->sdioh, true);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700116}
117
Roland Vossen127aa5c2011-07-05 22:05:58 +0200118int brcmf_sdcard_intr_disable(struct brcmf_sdio_card *card)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700119{
Roland Vossen62dd6562011-07-05 22:05:57 +0200120 ASSERT(card);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700121
Roland Vossen62dd6562011-07-05 22:05:57 +0200122 return brcmf_sdioh_interrupt_set(card->sdioh, false);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700123}
124
Roland Vossen127aa5c2011-07-05 22:05:58 +0200125int brcmf_sdcard_intr_reg(struct brcmf_sdio_card *card,
126 brcmf_sdiocard_cb_fn_t fn,
127 void *argh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700128{
Roland Vossen62dd6562011-07-05 22:05:57 +0200129 ASSERT(card);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700130
Roland Vossen62dd6562011-07-05 22:05:57 +0200131 return brcmf_sdioh_interrupt_register(card->sdioh, fn, argh);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700132}
133
Roland Vossen127aa5c2011-07-05 22:05:58 +0200134int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card *card)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700135{
Roland Vossen62dd6562011-07-05 22:05:57 +0200136 ASSERT(card);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700137
Roland Vossen62dd6562011-07-05 22:05:57 +0200138 return brcmf_sdioh_interrupt_deregister(card->sdioh);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700139}
140
Roland Vossen127aa5c2011-07-05 22:05:58 +0200141int brcmf_sdcard_devremove_reg(struct brcmf_sdio_card *card,
142 brcmf_sdiocard_cb_fn_t fn,
143 void *argh)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700144{
Roland Vossen127aa5c2011-07-05 22:05:58 +0200145 ASSERT(card);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700146
147 /* don't support yet */
Roland Vossene10d82d2011-05-03 11:35:19 +0200148 return -ENOTSUPP;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700149}
150
Roland Vossen127aa5c2011-07-05 22:05:58 +0200151u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_card *card, uint fnc_num, u32 addr,
152 int *err)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700153{
Roland Vossen3c793822011-06-29 16:47:23 -0700154 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700155#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -0700156 s32 retry = 0;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700157#endif
Greg Kroah-Hartman3fd79f72010-10-05 10:11:12 -0700158 u8 data = 0;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700159
Roland Vossen62dd6562011-07-05 22:05:57 +0200160 if (!card)
161 card = l_card;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700162
Roland Vossen62dd6562011-07-05 22:05:57 +0200163 ASSERT(card->init_success);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700164
165#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
166 do {
167 if (retry) /* wait for 1 ms till bus get settled down */
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +0200168 udelay(1000);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700169#endif
170 status =
Roland Vossen62dd6562011-07-05 22:05:57 +0200171 brcmf_sdioh_cfg_read(card->sdioh, fnc_num, addr,
Greg Kroah-Hartman3fd79f72010-10-05 10:11:12 -0700172 (u8 *) &data);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700173#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
Roland Vossen67f72be2011-06-29 16:47:56 -0700174 } while (status != 0
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700175 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
176#endif
177 if (err)
Roland Vossen67f72be2011-06-29 16:47:56 -0700178 *err = status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700179
Roland Vossen62dd6562011-07-05 22:05:57 +0200180 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700181 __func__, fnc_num, addr, data));
182
183 return data;
184}
185
186void
Roland Vossen127aa5c2011-07-05 22:05:58 +0200187brcmf_sdcard_cfg_write(struct brcmf_sdio_card *card, uint fnc_num, u32 addr,
188 u8 data, int *err)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700189{
Roland Vossen3c793822011-06-29 16:47:23 -0700190 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700191#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -0700192 s32 retry = 0;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700193#endif
194
Roland Vossen62dd6562011-07-05 22:05:57 +0200195 if (!card)
196 card = l_card;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700197
Roland Vossen62dd6562011-07-05 22:05:57 +0200198 ASSERT(card->init_success);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700199
200#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
201 do {
202 if (retry) /* wait for 1 ms till bus get settled down */
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +0200203 udelay(1000);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700204#endif
205 status =
Roland Vossen62dd6562011-07-05 22:05:57 +0200206 brcmf_sdioh_cfg_write(card->sdioh, fnc_num, addr,
Greg Kroah-Hartman3fd79f72010-10-05 10:11:12 -0700207 (u8 *) &data);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700208#ifdef SDIOH_API_ACCESS_RETRY_LIMIT
Roland Vossen67f72be2011-06-29 16:47:56 -0700209 } while (status != 0
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700210 && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT));
211#endif
212 if (err)
Roland Vossen67f72be2011-06-29 16:47:56 -0700213 *err = status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700214
Roland Vossen62dd6562011-07-05 22:05:57 +0200215 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n",
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700216 __func__, fnc_num, addr, data));
217}
218
Roland Vossen127aa5c2011-07-05 22:05:58 +0200219u32 brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card *card, uint fnc_num,
220 u32 addr, int *err)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700221{
Roland Vossen3c793822011-06-29 16:47:23 -0700222 int status;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -0700223 u32 data = 0;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700224
Roland Vossen62dd6562011-07-05 22:05:57 +0200225 if (!card)
226 card = l_card;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700227
Roland Vossen62dd6562011-07-05 22:05:57 +0200228 ASSERT(card->init_success);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700229
Roland Vossen62dd6562011-07-05 22:05:57 +0200230 status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
Roland Vossen54ca2962011-06-29 16:46:59 -0700231 SDIOH_READ, fnc_num, addr, &data, 4);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700232
233 if (err)
Roland Vossen67f72be2011-06-29 16:47:56 -0700234 *err = status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700235
Roland Vossen62dd6562011-07-05 22:05:57 +0200236 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700237 __func__, fnc_num, addr, data));
238
239 return data;
240}
241
242void
Roland Vossen127aa5c2011-07-05 22:05:58 +0200243brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card *card, uint fnc_num,
244 u32 addr, u32 data, int *err)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700245{
Roland Vossen3c793822011-06-29 16:47:23 -0700246 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700247
Roland Vossen62dd6562011-07-05 22:05:57 +0200248 if (!card)
249 card = l_card;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700250
Roland Vossen62dd6562011-07-05 22:05:57 +0200251 ASSERT(card->init_success);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700252
253 status =
Roland Vossen62dd6562011-07-05 22:05:57 +0200254 brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700255 SDIOH_WRITE, fnc_num, addr, &data, 4);
256
257 if (err)
Roland Vossen67f72be2011-06-29 16:47:56 -0700258 *err = status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700259
Roland Vossen62dd6562011-07-05 22:05:57 +0200260 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n",
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700261 __func__, fnc_num, addr, data));
262}
263
Roland Vossen127aa5c2011-07-05 22:05:58 +0200264int brcmf_sdcard_cis_read(struct brcmf_sdio_card *card, uint func, u8 * cis,
265 uint length)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700266{
Roland Vossen3c793822011-06-29 16:47:23 -0700267 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700268
Greg Kroah-Hartman3fd79f72010-10-05 10:11:12 -0700269 u8 *tmp_buf, *tmp_ptr;
270 u8 *ptr;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700271 bool ascii = func & ~0xf;
272 func &= 0x7;
273
Roland Vossen62dd6562011-07-05 22:05:57 +0200274 if (!card)
275 card = l_card;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700276
Roland Vossen62dd6562011-07-05 22:05:57 +0200277 ASSERT(card->init_success);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700278 ASSERT(cis);
279 ASSERT(length <= SBSDIO_CIS_SIZE_LIMIT);
280
Roland Vossen62dd6562011-07-05 22:05:57 +0200281 status = brcmf_sdioh_cis_read(card->sdioh, func, cis, length);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700282
283 if (ascii) {
284 /* Move binary bits to tmp and format them
285 into the provided buffer. */
mike.rapoport@gmail.com5fcc1fc2010-10-13 00:09:10 +0200286 tmp_buf = kmalloc(length, GFP_ATOMIC);
Jason Cooperc74c95c2010-09-30 15:15:35 -0400287 if (tmp_buf == NULL) {
Roland Vossen62dd6562011-07-05 22:05:57 +0200288 BRCMF_SD_ERROR(("%s: out of memory\n", __func__));
Roland Vossene10d82d2011-05-03 11:35:19 +0200289 return -ENOMEM;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700290 }
Stanislav Fomichev02160692011-02-15 01:05:10 +0300291 memcpy(tmp_buf, cis, length);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700292 for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4);
293 tmp_ptr++) {
294 ptr += sprintf((char *)ptr, "%.2x ", *tmp_ptr & 0xff);
295 if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0)
296 ptr += sprintf((char *)ptr, "\n");
297 }
mike.rapoport@gmail.com182acb32010-10-13 00:09:12 +0200298 kfree(tmp_buf);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700299 }
300
Roland Vossen67f72be2011-06-29 16:47:56 -0700301 return status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700302}
303
Roland Vossen127aa5c2011-07-05 22:05:58 +0200304static int
305brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_card *card, u32 address)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700306{
307 int err = 0;
Roland Vossen62dd6562011-07-05 22:05:57 +0200308 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700309 (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
310 if (!err)
Roland Vossen62dd6562011-07-05 22:05:57 +0200311 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
Roland Vossen54ca2962011-06-29 16:46:59 -0700312 SBSDIO_FUNC1_SBADDRMID,
313 (address >> 16) & SBSDIO_SBADDRMID_MASK,
314 &err);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700315 if (!err)
Roland Vossen62dd6562011-07-05 22:05:57 +0200316 brcmf_sdcard_cfg_write(card, SDIO_FUNC_1,
Roland Vossen54ca2962011-06-29 16:46:59 -0700317 SBSDIO_FUNC1_SBADDRHIGH,
318 (address >> 24) & SBSDIO_SBADDRHIGH_MASK,
319 &err);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700320
321 return err;
322}
323
Roland Vossen127aa5c2011-07-05 22:05:58 +0200324u32 brcmf_sdcard_reg_read(struct brcmf_sdio_card *card, u32 addr, uint size)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700325{
Roland Vossen3c793822011-06-29 16:47:23 -0700326 int status;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -0700327 u32 word = 0;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700328 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
329
Roland Vossen62dd6562011-07-05 22:05:57 +0200330 BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, ", __func__, addr));
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700331
Roland Vossen62dd6562011-07-05 22:05:57 +0200332 if (!card)
333 card = l_card;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700334
Roland Vossen62dd6562011-07-05 22:05:57 +0200335 ASSERT(card->init_success);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700336
Roland Vossen62dd6562011-07-05 22:05:57 +0200337 if (bar0 != card->sbwad) {
338 if (brcmf_sdcard_set_sbaddr_window(card, bar0))
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700339 return 0xFFFFFFFF;
340
Roland Vossen62dd6562011-07-05 22:05:57 +0200341 card->sbwad = bar0;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700342 }
343
344 addr &= SBSDIO_SB_OFT_ADDR_MASK;
345 if (size == 4)
346 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
347
Roland Vossen62dd6562011-07-05 22:05:57 +0200348 status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700349 SDIOH_READ, SDIO_FUNC_1, addr, &word, size);
350
Roland Vossen62dd6562011-07-05 22:05:57 +0200351 card->regfail = (status != 0);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700352
Roland Vossen62dd6562011-07-05 22:05:57 +0200353 BRCMF_SD_INFO(("u32data = 0x%x\n", word));
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700354
355 /* if ok, return appropriately masked word */
Roland Vossen67f72be2011-06-29 16:47:56 -0700356 if (status == 0) {
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700357 switch (size) {
Greg Kroah-Hartman3fd79f72010-10-05 10:11:12 -0700358 case sizeof(u8):
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700359 return word & 0xff;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700360 case sizeof(u16):
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700361 return word & 0xffff;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -0700362 case sizeof(u32):
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700363 return word;
364 default:
Roland Vossen62dd6562011-07-05 22:05:57 +0200365 card->regfail = true;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700366
367 }
368 }
369
370 /* otherwise, bad sdio access or invalid size */
Roland Vossen62dd6562011-07-05 22:05:57 +0200371 BRCMF_SD_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__,
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700372 addr, size));
373 return 0xFFFFFFFF;
374}
375
Roland Vossen127aa5c2011-07-05 22:05:58 +0200376u32 brcmf_sdcard_reg_write(struct brcmf_sdio_card *card, u32 addr, uint size,
377 u32 data)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700378{
Roland Vossen3c793822011-06-29 16:47:23 -0700379 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700380 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
381 int err = 0;
382
Roland Vossen62dd6562011-07-05 22:05:57 +0200383 BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n",
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700384 __func__, addr, size * 8, data));
385
Roland Vossen62dd6562011-07-05 22:05:57 +0200386 if (!card)
387 card = l_card;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700388
Roland Vossen62dd6562011-07-05 22:05:57 +0200389 ASSERT(card->init_success);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700390
Roland Vossen62dd6562011-07-05 22:05:57 +0200391 if (bar0 != card->sbwad) {
392 err = brcmf_sdcard_set_sbaddr_window(card, bar0);
Jason Cooperc74c95c2010-09-30 15:15:35 -0400393 if (err)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700394 return err;
395
Roland Vossen62dd6562011-07-05 22:05:57 +0200396 card->sbwad = bar0;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700397 }
398
399 addr &= SBSDIO_SB_OFT_ADDR_MASK;
400 if (size == 4)
401 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
402 status =
Roland Vossen62dd6562011-07-05 22:05:57 +0200403 brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL,
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700404 SDIOH_WRITE, SDIO_FUNC_1, addr, &data, size);
Roland Vossen62dd6562011-07-05 22:05:57 +0200405 card->regfail = (status != 0);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700406
Roland Vossen67f72be2011-06-29 16:47:56 -0700407 if (status == 0)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700408 return 0;
409
Roland Vossen62dd6562011-07-05 22:05:57 +0200410 BRCMF_SD_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n",
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700411 __func__, data, addr, size));
412 return 0xFFFFFFFF;
413}
414
Roland Vossen127aa5c2011-07-05 22:05:58 +0200415bool brcmf_sdcard_regfail(struct brcmf_sdio_card *card)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700416{
Roland Vossen127aa5c2011-07-05 22:05:58 +0200417 return card->regfail;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700418}
419
420int
Roland Vossen127aa5c2011-07-05 22:05:58 +0200421brcmf_sdcard_recv_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
422 uint flags,
423 u8 *buf, uint nbytes, struct sk_buff *pkt,
424 brcmf_sdio_cmplt_fn_t complete, void *handle)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700425{
Roland Vossen3c793822011-06-29 16:47:23 -0700426 int status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700427 uint incr_fix;
428 uint width;
429 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
430 int err = 0;
431
Roland Vossen62dd6562011-07-05 22:05:57 +0200432 ASSERT(card);
433 ASSERT(card->init_success);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700434
Roland Vossen62dd6562011-07-05 22:05:57 +0200435 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700436 __func__, fn, addr, nbytes));
437
438 /* Async not implemented yet */
439 ASSERT(!(flags & SDIO_REQ_ASYNC));
440 if (flags & SDIO_REQ_ASYNC)
Roland Vossene10d82d2011-05-03 11:35:19 +0200441 return -ENOTSUPP;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700442
Roland Vossen62dd6562011-07-05 22:05:57 +0200443 if (bar0 != card->sbwad) {
444 err = brcmf_sdcard_set_sbaddr_window(card, bar0);
Jason Cooperc74c95c2010-09-30 15:15:35 -0400445 if (err)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700446 return err;
447
Roland Vossen62dd6562011-07-05 22:05:57 +0200448 card->sbwad = bar0;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700449 }
450
451 addr &= SBSDIO_SB_OFT_ADDR_MASK;
452
453 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
454 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
455 if (width == 4)
456 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
457
Roland Vossen62dd6562011-07-05 22:05:57 +0200458 status = brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
Roland Vossen54ca2962011-06-29 16:46:59 -0700459 incr_fix, SDIOH_READ, fn, addr, width, nbytes, buf, pkt);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700460
Roland Vossen67f72be2011-06-29 16:47:56 -0700461 return status;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700462}
463
464int
Roland Vossen127aa5c2011-07-05 22:05:58 +0200465brcmf_sdcard_send_buf(struct brcmf_sdio_card *card, u32 addr, uint fn,
466 uint flags, u8 *buf, uint nbytes, void *pkt,
467 brcmf_sdio_cmplt_fn_t complete, void *handle)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700468{
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700469 uint incr_fix;
470 uint width;
471 uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
472 int err = 0;
473
Roland Vossen62dd6562011-07-05 22:05:57 +0200474 ASSERT(card);
475 ASSERT(card->init_success);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700476
Roland Vossen62dd6562011-07-05 22:05:57 +0200477 BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n",
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700478 __func__, fn, addr, nbytes));
479
480 /* Async not implemented yet */
481 ASSERT(!(flags & SDIO_REQ_ASYNC));
482 if (flags & SDIO_REQ_ASYNC)
Roland Vossene10d82d2011-05-03 11:35:19 +0200483 return -ENOTSUPP;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700484
Roland Vossen62dd6562011-07-05 22:05:57 +0200485 if (bar0 != card->sbwad) {
486 err = brcmf_sdcard_set_sbaddr_window(card, bar0);
Jason Cooperc74c95c2010-09-30 15:15:35 -0400487 if (err)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700488 return err;
489
Roland Vossen62dd6562011-07-05 22:05:57 +0200490 card->sbwad = bar0;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700491 }
492
493 addr &= SBSDIO_SB_OFT_ADDR_MASK;
494
495 incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC;
496 width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
497 if (width == 4)
498 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
499
Roland Vossen62dd6562011-07-05 22:05:57 +0200500 return brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
Roland Vossen54ca2962011-06-29 16:46:59 -0700501 incr_fix, SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700502}
503
Roland Vossen127aa5c2011-07-05 22:05:58 +0200504int brcmf_sdcard_rwdata(struct brcmf_sdio_card *card, uint rw, u32 addr,
505 u8 *buf, uint nbytes)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700506{
Roland Vossen62dd6562011-07-05 22:05:57 +0200507 ASSERT(card);
508 ASSERT(card->init_success);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700509 ASSERT((addr & SBSDIO_SBWINDOW_MASK) == 0);
510
511 addr &= SBSDIO_SB_OFT_ADDR_MASK;
512 addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
513
Roland Vossen62dd6562011-07-05 22:05:57 +0200514 return brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO,
Roland Vossen54ca2962011-06-29 16:46:59 -0700515 SDIOH_DATA_INC, (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1,
516 addr, 4, nbytes, buf, NULL);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700517}
518
Roland Vossen127aa5c2011-07-05 22:05:58 +0200519int brcmf_sdcard_abort(struct brcmf_sdio_card *card, uint fn)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700520{
Roland Vossen62dd6562011-07-05 22:05:57 +0200521 return brcmf_sdioh_abort(card->sdioh, fn);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700522}
523
Roland Vossen127aa5c2011-07-05 22:05:58 +0200524int brcmf_sdcard_start(struct brcmf_sdio_card *card, int stage)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700525{
Roland Vossen62dd6562011-07-05 22:05:57 +0200526 return brcmf_sdioh_start(card->sdioh, stage);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700527}
528
Roland Vossen127aa5c2011-07-05 22:05:58 +0200529int brcmf_sdcard_stop(struct brcmf_sdio_card *card)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700530{
Roland Vossen62dd6562011-07-05 22:05:57 +0200531 return brcmf_sdioh_stop(card->sdioh);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700532}
533
Roland Vossen127aa5c2011-07-05 22:05:58 +0200534int brcmf_sdcard_query_device(struct brcmf_sdio_card *card)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700535{
Roland Vossen62dd6562011-07-05 22:05:57 +0200536 card->vendevid = (PCI_VENDOR_ID_BROADCOM << 16) | 0;
537 return card->vendevid;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700538}
539
Roland Vossen127aa5c2011-07-05 22:05:58 +0200540uint brcmf_sdcard_query_iofnum(struct brcmf_sdio_card *card)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700541{
Roland Vossen62dd6562011-07-05 22:05:57 +0200542 if (!card)
543 card = l_card;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700544
Roland Vossen62dd6562011-07-05 22:05:57 +0200545 return brcmf_sdioh_query_iofnum(card->sdioh);
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700546}
547
Roland Vossen127aa5c2011-07-05 22:05:58 +0200548void *brcmf_sdcard_get_sdioh(struct brcmf_sdio_card *card)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700549{
Roland Vossen127aa5c2011-07-05 22:05:58 +0200550 ASSERT(card);
551 return card->sdioh;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700552}
553
554/* Function to pass device-status bits to DHD. */
Roland Vossen127aa5c2011-07-05 22:05:58 +0200555u32 brcmf_sdcard_get_dstatus(struct brcmf_sdio_card *card)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700556{
557 return 0;
558}
559
Roland Vossen127aa5c2011-07-05 22:05:58 +0200560u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card *card)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700561{
Roland Vossen62dd6562011-07-05 22:05:57 +0200562 if (!card)
563 card = l_card;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700564
Roland Vossen62dd6562011-07-05 22:05:57 +0200565 return card->sbwad;
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700566}
567
Roland Vossen127aa5c2011-07-05 22:05:58 +0200568void brcmf_sdcard_chipinfo(struct brcmf_sdio_card *card, u32 chip, u32 chiprev)
Henry Ptasinskicf2b4482010-09-20 22:33:12 -0700569{
570 return;
571}